﻿//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//   Copyright(c) 2023, Hexagon's Asset Lifecycle Intelligence.All rights reserved.

//   ProgID: SEIDDP,Ingr.SP3D.SEIDDP.IMRSV
//   Author:  xingheng yu
//   Creation Date:     2023-03-07
//   Description: IMRSV

//   Change History:
//   version        data              who                change description
//   =======        ===========       ==============     ==========================================================================================
//   2.0.0.6        2024-11-04        xingheng yu        创建
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++


using System;
using System.IO;
using System.Collections.ObjectModel;
using Ingr.SP3D.Common.Middle;
using Ingr.SP3D.Common.Middle.Services;
using Ingr.SP3D.Common.Exceptions;
using Ingr.SP3D.CommonSymbolFunctions;
using Ingr.SP3D.ReferenceData.Middle;
using System.Windows.Forms;
using Ingr.SP3D.Equipment.Middle;

namespace Ingr.SP3D.SEIDDP
{
    [CacheOption(CacheOptionType.NonCached)]
    [VariableOutputs]
    [SymbolVersion("2.0.0.6")]
    public class IMRSV : CustomSymbolDefinition //继承后者的类
    {
        /// <summary>
        /// 构造函数
        /// </summary>
        public IMRSV() : base()
        {
            //有多少个port，就会重复进来多少次
            //这个dll就类似于pid的datasource对象           
            string DllPath = MiddleServiceProvider.SiteMgr.ActiveSite.ActivePlant.PlantCatalog.SymbolShare + @"\Custom Symbols\CommonSymbolFunctions.dll";
            if (File.Exists(DllPath) == false)
            {
                throw new Exception(@"SharedContent\Custom Symbols\CommonSymbolFunctions.dll 未找到，symbol无法工作");
            }
            else
            {
                Ingr.SP3D.Content.CommonSymbolFunctionLoader.Load();
            }
            defaultPartDataBasis = 15;
        }

        //DefinitionName/ProgID of this symbol is SEIDDP,Ingr.SP3D.SEIDDP.DIS01
        SymbolGeometryHelper oGemHelper = new SymbolGeometryHelper();
        double parD2, parD3, parD4, parD5, parD6, parD7, parD8, parD9, parD10, parD11, parD12, parInsulationThickness;
        /// <summary>
        /// PORT3 4的宽度
        /// </summary>
        double parD16;
        /// <summary>
        /// 前后直管段
        /// </summary>
        double parD13, parD14;
        int defaultPartDataBasis;
        double parPortIndex4, parPortIndex3, parPortIndex2, parPortIndex1, parNpd4, parNpd3, parNpd2, parNpd1, parNpd;
        int parEndPreparation, parScheduleThickness, parEndStandard, parPressureRating, parFlowDirection,
            parEndPreparation1, parScheduleThickness1, parEndStandard1, parPressureRating1, parFlowDirection1,
            parEndPreparation2, parScheduleThickness2, parEndStandard2, parPressureRating2, parFlowDirection2,
            parEndPreparation3, parScheduleThickness3, parEndStandard3, parPressureRating3, parFlowDirection3,
            parEndPreparation4, parScheduleThickness4, parEndStandard4, parPressureRating4, parFlowDirection4;
        double parPipingPointBasis3, parPipingPointBasis4;

        string parNpdUnitType, parNpdUnitType1, parId1, parNpdUnitType2, parId2, parNpdUnitType3, parId3, parNpdUnitType4, parId4;

        #region "Definition of Inputs" 
        //这个1 2 3 4代表了唯一的序号，先后顺序。因为所有的输入参数被视为一个集合
        //名字要和bulkload表里的属性名字一致。顺序、描述其实无所谓,外部的参数会根据Name自动匹配到对应的某一个参数中。
        //但是需要要连续，不能中间有空的
        // Token: 0x0400003A RID: 58
        [InputCatalogPart(1)]
        public InputCatalogPart partFclt;
        [InputDouble(2, "InstrumentLength", "Instrument Length", 0.333375)]
        public InputDouble m_InstrumentLength;
        [InputDouble(3, "InstrumentLength1", "Instrument Length1", 0.333375)]
        public InputDouble m_InstrumentLength1;
        [InputDouble(4, "InstrumentLength2", "Instrument Length2", 0.333375)]
        public InputDouble m_InstrumentLength2;
        [InputDouble(5, "InstrumentLength3", "Instrument Length3", 0.333375)]
        public InputDouble m_InstrumentLength3;
        [InputDouble(6, "InstrumentDiameter", "Venturi Diameter", 0.05)]
        public InputDouble m_InstrumentDiameter;
        [InputDouble(7, "NozzleOffset", "Nozzle Offset", 0.1524)]
        public InputDouble m_NozzleOffset;
        [InputDouble(8, "NozzleOffset1", "Nozzle Offset1", 0.81915)]
        public InputDouble m_NozzleOffset1;
        [InputDouble(9, "NozzleOffset2", "Nozzle Offset2", 0.07)]
        public InputDouble m_NozzleOffset2;
        [InputDouble(10, "NozzleOffset3", "Nozzle Offset3", 0.07)]
        public InputDouble m_NozzleOffset3;
        [InputDouble(11, "PortRotation1", "Port Rotation of Nozz3", 0.785398163397448)]
        public InputDouble m_PortRotation1;
        [InputDouble(12, "PortRotation2", "Port Rotation of Nozz4", 0.785398163397448)]
        public InputDouble m_PortRotation2;
        [InputDouble(13, "InsulationThickness", "Insulation Thickness", 0.025)]
        public InputDouble m_InsulationThickness;
        [InputDouble(14, "Npd", "NPD", 100.0)]
        public InputDouble m_Npd;
        [InputDouble(15, "EndPreparation", "EndPreparation", 21.0)]
        public InputDouble m_EndPreparation;
        [InputDouble(16, "ScheduleThickness", "ScheduleThickness", 100.0)]
        public InputDouble m_ScheduleThickness;
        [InputDouble(17, "EndStandard", "EndStandard", 5.0)]
        public InputDouble m_EndStandard;
        [InputDouble(18, "PressureRating", "PressureRating", 35.0)]
        public InputDouble m_PressureRating;
        [InputDouble(19, "FlowDirection", "FlowDirection", 3.0)]
        public InputDouble m_FlowDirection;
        [InputDouble(20, "PortIndex1", "PortIndex1", 1.0)]
        public InputDouble m_PortIndex1;
        [InputDouble(21, "Npd1", "NPD1", 0.0)]
        public InputDouble m_Npd1;
        [InputDouble(22, "EndPreparation1", "EndPreparation1", 0.0)]
        public InputDouble m_EndPreparation1;
        [InputDouble(23, "ScheduleThickness1", "ScheduleThickness1", 0.0)]
        public InputDouble m_ScheduleThickness1;
        [InputDouble(24, "EndStandard1", "EndStandard1", 0.0)]
        public InputDouble m_EndStandard1;
        [InputDouble(25, "PressureRating1", "PressureRating1", 0.0)]
        public InputDouble m_PressureRating1;
        [InputDouble(26, "FlowDirection1", "FlowDirection1", 0.0)]
        public InputDouble m_FlowDirection1;
        [InputDouble(27, "PortIndex2", "PortIndex2", 2.0)]
        public InputDouble m_PortIndex2;
        [InputDouble(28, "Npd2", "NPD2", 0.0)]
        public InputDouble m_Npd2;
        [InputDouble(29, "EndPreparation2", "EndPreparation2", 0.0)]
        public InputDouble m_EndPreparation2;
        [InputDouble(30, "ScheduleThickness2", "ScheduleThickness2", 0.0)]
        public InputDouble m_ScheduleThickness2;
        [InputDouble(31, "EndStandard2", "EndStandard2", 0.0)]
        public InputDouble m_EndStandard2;
        [InputDouble(32, "PressureRating2", "PressureRating2", 0.0)]
        public InputDouble m_PressureRating2;
        [InputDouble(33, "FlowDirection2", "FlowDirection2", 0.0)]
        public InputDouble m_FlowDirection2;
        [InputDouble(34, "PortIndex3", "PortIndex3", 3.0)]
        public InputDouble m_PortIndex3;
        [InputDouble(35, "Npd3", "NPD3", 0.0)]
        public InputDouble m_Npd3;
        [InputDouble(36, "EndPreparation3", "EndPreparation3", 0.0)]
        public InputDouble m_EndPreparation3;
        [InputDouble(37, "ScheduleThickness3", "ScheduleThickness3", 0.0)]
        public InputDouble m_ScheduleThickness3;
        [InputDouble(38, "EndStandard3", "EndStandard3", 0.0)]
        public InputDouble m_EndStandard3;
        [InputDouble(39, "PressureRating3", "PressureRating3", 0.0)]
        public InputDouble m_PressureRating3;
        [InputDouble(40, "FlowDirection3", "FlowDirection3", 0.0)]
        public InputDouble m_FlowDirection3;
        [InputDouble(41, "PortIndex4", "PortIndex4", 4.0)]
        public InputDouble m_PortIndex4;
        [InputDouble(42, "Npd4", "NPD4", 0.0)]
        public InputDouble m_Npd4;
        [InputDouble(43, "EndPreparation4", "EndPreparation4", 0.0)]
        public InputDouble m_EndPreparation4;
        [InputDouble(44, "ScheduleThickness4", "ScheduleThickness4", 0.0)]
        public InputDouble m_ScheduleThickness4;
        [InputDouble(45, "EndStandard4", "EndStandard4", 0.0)]
        public InputDouble m_EndStandard4;
        [InputDouble(46, "PressureRating4", "PressureRating4", 0.0)]
        public InputDouble m_PressureRating4;
        [InputDouble(47, "FlowDirection4", "FlowDirection4", 0.0)]
        public InputDouble m_FlowDirection4;
        [InputDouble(48, "PipingPointBasis3", "PipingPointBasis3", 50.0, true)]
        public InputDouble m_PipingPointBasis3;
        [InputDouble(49, "PipingPointBasis4", "PipingPointBasis4", 50.0, true)]
        public InputDouble m_PipingPointBasis4;
        [InputString(50, "Id1", "Id1", "VNoz1")]
        public InputString m_Id1;
        [InputString(51, "Id2", "Id2", "VNoz2")]
        public InputString m_Id2;
        [InputString(52, "Id3", "Id3", "VNoz3")]
        public InputString m_Id3;
        [InputString(53, "Id4", "Id4", "VNoz4")]
        public InputString m_Id4;
        [InputString(54, "NpdUnitType", "Npd Unit Type", "mm")]
        public InputString m_NpdUnitType;
        [InputString(55, "NpdUnitType1", "Npd Unit Type 1", "")]
        public InputString m_NpdUnitType1;
        [InputString(56, "NpdUnitType2", "Npd Unit Type 2", "")]
        public InputString m_NpdUnitType2;
        [InputString(57, "NpdUnitType3", "Npd Unit Type 3", "")]
        public InputString m_NpdUnitType3;
        [InputString(58, "NpdUnitType4", "Npd Unit Type 4", "")]
        public InputString m_NpdUnitType4;

        [InputDouble(59, "InstrumentRadius", "D16", 0.1, true)]
        public InputDouble m_D16;
        [InputDouble(60, "InstrumentLength4", "Instrument Length4", 0.333375)]
        public InputDouble m_D13;
        [InputDouble(61, "InstrumentLength5", "Instrument Length5", 0.333375)]
        public InputDouble m_D14;
        #endregion

        #region "Definitions of Aspects and their Outputs"
        //名字要在实际outputs.add时，匹配上
        [Aspect("Physical", "Physical", AspectID.SimplePhysical)]
        [SymbolOutput("VNoz1", "Nozzle 1")]
        [SymbolOutput("VNoz2", "Nozzle 2")]
        [SymbolOutput("VNoz3", "Nozzle 3")]
        [SymbolOutput("VNoz4", "Nozzle 4")]
        [SymbolOutput("CylinderBody1", "Cylinder Body1")]
        [SymbolOutput("ReducingCone", "Reducing Cone")]
        [SymbolOutput("CylinderBody2", "Cylinder Body2")]
        [SymbolOutput("DivergingCone", "Diverging Cone")]
        [SymbolOutput("CylinderBody3", "Cylinder Body3")]
        [SymbolOutput("CylinderBody4", "Cylinder Body4")]
        [SymbolOutput("CylinderBody5", "Cylinder Body5")]
        [SymbolOutput("CylinderBody6", "Cylinder Body6")]        
        [SymbolOutput("CylinderLineOut", "CylinderLineOut")]
        public AspectDefinition m_Physical;  //Aspect可以理解为SymbolOutput的集合

        [Aspect("Insulation", "Insulation", AspectID.Insulation)]
        [SymbolOutput("Nozz3BodyIns", "Nozzle3 Body Insulation")]
        [SymbolOutput("Nozz4BodyIns", "Nozzle4 Body Insulation")]
        [SymbolOutput("VenturiBodyIns", "Venturi Body Insulation")]
        public AspectDefinition m_Insulation;

        #endregion

        #region "Construct Outputs"

        /// <summary>
        /// 造型
        /// </summary>
        protected override void ConstructOutputs()
        {
            try
            {
                parD2 = m_InstrumentLength.Value;
                parD3 = m_InstrumentLength1.Value;
                parD4 = m_InstrumentLength2.Value;
                parD5 = m_InstrumentLength3.Value;
                parD6 = m_InstrumentDiameter.Value;
                parD7 = m_NozzleOffset.Value;
                parD8 = m_NozzleOffset1.Value;
                parD9 = m_NozzleOffset2.Value;
                parD10 = m_NozzleOffset3.Value;
                parD11 = m_PortRotation1.Value;
                parD12 = m_PortRotation2.Value;
                parD13 = m_D13.Value;
                parD14 = m_D14.Value;
                parD16 = m_D16.Value;
                parInsulationThickness = m_InsulationThickness.Value;
                parNpd = m_Npd.Value;
                parEndPreparation = (int)m_EndPreparation.Value;
                parScheduleThickness = (int)m_ScheduleThickness.Value;
                parEndStandard = (int)m_EndStandard.Value;
                parPressureRating = (int)m_PressureRating.Value;
                parFlowDirection = (int)m_FlowDirection.Value;
                parPortIndex1 = m_PortIndex1.Value;
                parNpd1 = m_Npd1.Value;
                parEndPreparation1 = (int)m_EndPreparation1.Value;
                parScheduleThickness1 = (int)m_ScheduleThickness1.Value;
                parEndStandard1 = (int)m_EndStandard1.Value;
                parPressureRating1 = (int)m_PressureRating1.Value;
                parFlowDirection1 = (int)m_FlowDirection1.Value;
                if (parFlowDirection1 == 0.0)
                {
                    parFlowDirection1 = (int)m_FlowDirection.Value;
                }
                parPortIndex2 = m_PortIndex2.Value;
                parNpd2 = m_Npd2.Value;
                parEndPreparation2 = (int)m_EndPreparation2.Value;
                parScheduleThickness2 = (int)m_ScheduleThickness2.Value;
                parEndStandard2 = (int)m_EndStandard2.Value;
                parPressureRating2 = (int)m_PressureRating2.Value;
                parFlowDirection2 = (int)m_FlowDirection2.Value;
                if (parFlowDirection2 == 0.0)
                {
                    parFlowDirection2 = (int)m_FlowDirection.Value;
                }
                parPortIndex3 = m_PortIndex3.Value;
                parNpd3 = m_Npd3.Value;
                parEndPreparation3 = (int)m_EndPreparation3.Value;
                parScheduleThickness3 = 1;// (int)m_ScheduleThickness3.Value;
                parEndStandard3 = (int)m_EndStandard3.Value;
                parPressureRating3 = (int)m_PressureRating3.Value;
                parFlowDirection3 = (int)m_FlowDirection3.Value;
                if (parFlowDirection3 == 0.0)
                {
                    parFlowDirection3 = (int)m_FlowDirection.Value;
                }
                parPortIndex4 = m_PortIndex4.Value;
                parNpd4 = m_Npd4.Value;
                parEndPreparation4 = (int)m_EndPreparation4.Value;
                parScheduleThickness4 = 1;// (int)m_ScheduleThickness4.Value;
                parEndStandard4 = (int)m_EndStandard4.Value;
                parPressureRating4 = (int)m_PressureRating4.Value;
                parFlowDirection4 = (int)m_FlowDirection4.Value;
                if (parFlowDirection4 == 0.0)
                {
                    parFlowDirection4 = (int)m_FlowDirection.Value;
                }
                parPipingPointBasis3 = m_PipingPointBasis3.Value;
                parPipingPointBasis4 = m_PipingPointBasis4.Value;
                parId1 = m_Id1.Value;
                parId2 = m_Id2.Value;
                parId3 = m_Id3.Value;
                parId4 = m_Id4.Value;
                parNpdUnitType = m_NpdUnitType.Value;
                parNpdUnitType1 = m_NpdUnitType1.Value;
                parNpdUnitType2 = m_NpdUnitType2.Value;
                parNpdUnitType3 = m_NpdUnitType3.Value;
                parNpdUnitType4 = m_NpdUnitType4.Value;
                // 角度会自动变为弧度进来
                // 长度会自动变为m为单位进来


                PipeComponent DDP = (PipeComponent)partFclt.Value;  //Get the part from the catalog
                SP3DConnection connection = OccurrenceConnection;
                int partDataBasis = DDP.PartDataBasis;
                //var partDataBasis = DDP.GetPropertyValue("IJDPipeComponent", "PartDataBasis");//如果要取part上的某个属性，可以这样。和spf很像

                RunIMRSV(DDP, connection, oGemHelper);


            }
            catch (Exception ex) // General Unhandled exception
            {
                throw (ex);
            }
        }

        #endregion



        #region "Geometry Construction"
        /// <summary>
        /// 最初的模板，该函数是根据不同的partDataBasis的值，来进行不同的处理
        /// </summary>
        /// <param name="DDP"></param>
        /// <param name="OccurrenceConnection"></param>
        private void RunIMRSV(PipeComponent DDP, SP3DConnection connection, SymbolGeometryHelper oGemHelper)
        {
            double Port34Radius = 0;
            try
            {
                if (parEndPreparation3 == 301)
                {
                    parPressureRating3 = 1;
                }
                if (parEndPreparation4 == 301)
                {
                    parPressureRating4 = 1;
                }

                if (parD10 <= parD6 * 0.5)
                {
                    MessageBox.Show("D10不能小于D6的一半");
                    throw new Exception("D10不能小于D6的一半");
                }
                else
                {
                    Port34Radius = parD10 - parD6 * 0.5;
                    //parD10-(parD10 - parD6 * 0.5)*0.3
                    //
                }
            }
            catch
            {

            }
            try
            {
                // 第 1 个port
                // DDP 或者说 动态参数的情况，都要用这种方式先创建出port，而不能用下面这个
                // PipeNozzle port2 = PortHelper.CreatePipeNozzle(pipeComponent, connection, false, 2, new Position(0, D2, 0), new Vector(-1, 0, 0), true, true);
                PipeNozzle port1 = PortHelper.CreateDynamicPipePort(connection, 1, parNpd1, parNpdUnitType1, parEndPreparation1, parScheduleThickness1, parEndStandard1, parPressureRating1, parFlowDirection1, parId1, defaultPartDataBasis, false, new Position(-parD4 * 0.5 - parD3 - parD2 - parD13, 0, 0), new Vector(-1, 0, 0), true, true);
                m_Physical.Outputs.Add("PNoz1", port1);  //Nozzle1
                if (port1.PipingOutsideDiameter < parD9 * 2)
                {

                }
                else
                {
                    MessageBox.Show("D9不能小于文丘里管主体圆柱的半径。");
                    throw new Exception("D9不能小于文丘里管主体圆柱的半径");
                }
                // 第 2 个port
                PipeNozzle port2 = PortHelper.CreateDynamicPipePort(connection, 2, parNpd2, parNpdUnitType2, parEndPreparation2, parScheduleThickness2, parEndStandard2, parPressureRating2, parFlowDirection2, parId2, defaultPartDataBasis, false, new Position(parD4 * 0.5 + parD5 + parD14, 0, 0), new Vector(1, 0, 0), true, true);
                m_Physical.Outputs.Add("PNoz2", port2);

                // 第 3 个port
                PipeNozzle port3 = PortHelper.CreateDynamicPipePort(connection, 3, parNpd3, parNpdUnitType3, parEndPreparation3, parScheduleThickness3, parEndStandard3, parPressureRating3, parFlowDirection3, parId3, defaultPartDataBasis, false, new Position(-parD4 * 0.5 - parD3 - parD2 + parD7, parD9 * Math.Sin(parD11), parD9 * Math.Cos(parD11)), new Vector(0, Math.Sin(parD11), Math.Cos(parD11)), true, true);
                m_Physical.Outputs.Add("PNoz3", port3);

                // 第 4 个port
                PipeNozzle port4 = PortHelper.CreateDynamicPipePort(connection, 4, parNpd4, parNpdUnitType4, parEndPreparation4, parScheduleThickness4, parEndStandard4, parPressureRating4, parFlowDirection4, parId4, defaultPartDataBasis, false, new Position(-parD4 * 0.5 - parD3 - parD2 + parD8, parD10 * Math.Sin(parD12), parD10 * Math.Cos(parD12)), new Vector(0, Math.Sin(parD12), Math.Cos(parD12)), true, true);
                m_Physical.Outputs.Add("PNoz4", port4);

                //CylinderBody1(长度为D2+D13的）
                Position startPoint = new Position(-parD4 * 0.5 - parD3 - parD2 - parD13, 0, 0);
                Position endPoint = new Position(-parD4 * 0.5 - parD3, 0, 0);
                var body = Graphics3D.CreateCylinder(startPoint, endPoint, port1.PipingOutsideDiameter, true);
                m_Physical.Outputs.Add("CylinderBody1", body);

                //ReducingCone（长度为D3的圆台）
                Position centerBase = new Position(-parD4 * 0.5 - parD3, 0, 0);  //大头
                Position centerTop = new Position(-parD4 * 0.5, 0, 0);  //小头
                var body2 = Graphics3D.CreateCone(centerBase, centerTop, port1.PipingOutsideDiameter * 0.5, parD6 * 0.5, true);
                m_Physical.Outputs.Add("ReducingCone", body2);

                //CylinderBody2（D4的中心圆柱）
                startPoint = new Position(-parD4 * 0.5, 0, 0);
                endPoint = new Position(parD4 * 0.5, 0, 0);
                body = Graphics3D.CreateCylinder(startPoint, endPoint, parD6, true);
                m_Physical.Outputs.Add("CylinderBody2", body);

                //DivergingCone（长度为D5的圆台）
                centerBase = new Position(parD4 * 0.5, 0, 0);  //大头
                centerTop = new Position(parD4 * 0.5 + parD5, 0, 0);  //小头
                body2 = Graphics3D.CreateCone(centerBase, centerTop, parD6 * 0.5, port2.PipingOutsideDiameter * 0.5, true);
                m_Physical.Outputs.Add("DivergingCone", body2);


                //CylinderLineOut(长度为D14的）
                startPoint = new Position(parD4 * 0.5 + parD5, 0, 0);
                endPoint = new Position(parD4 * 0.5 + parD5 + parD14, 0, 0);
                body = Graphics3D.CreateCylinder(startPoint, endPoint, port1.PipingOutsideDiameter, true);
                m_Physical.Outputs.Add("CylinderLineOut", body);

                //CylinderBody3（port3的小圆柱）
                startPoint = new Position(-parD4 * 0.5 - parD3 - parD2 + parD7, parD9 * Math.Sin(parD11), parD9 * Math.Cos(parD11));
                endPoint = new Position(-parD4 * 0.5 - parD3 - parD2 + parD7, 0, 0);
                body = Graphics3D.CreateCylinder(startPoint, endPoint, port3.PipingOutsideDiameter, true);
                m_Physical.Outputs.Add("CylinderBody3", body);

                // port3上的支管上，代表可能有的操作元件 
                startPoint = new Position(-parD4 * 0.5 - parD3 - parD2 + parD7, parD9 * Math.Sin(parD11), parD9 * Math.Cos(parD11));
                endPoint = new Position(-parD4 * 0.5 - parD3 - parD2 + parD7, (parD9 - Port34Radius * 0.3) * Math.Sin(parD11), (parD9 - Port34Radius * 0.3) * Math.Cos(parD11));
                body = Graphics3D.CreateCylinder(startPoint, endPoint, parD16, true);
                m_Physical.Outputs.Add("CylinderBody5", body);

                //CylinderBody4（port4的小圆柱）
                startPoint = new Position(-parD4 * 0.5 - parD3 - parD2 + parD8, parD10 * Math.Sin(parD12), parD10 * Math.Cos(parD12));
                endPoint = new Position(-parD4 * 0.5 - parD3 - parD2 + parD8, 0, 0);
                body = Graphics3D.CreateCylinder(startPoint, endPoint, port4.PipingOutsideDiameter, true);
                m_Physical.Outputs.Add("CylinderBody4", body);

                // port4上的支管上，代表可能有的操作元件 
                startPoint = new Position(-parD4 * 0.5 - parD3 - parD2 + parD8, parD10 * Math.Sin(parD12), parD10 * Math.Cos(parD12));
                endPoint = new Position(-parD4 * 0.5 - parD3 - parD2 + parD8, (parD10 - Port34Radius * 0.3) * Math.Sin(parD12), (parD10 - Port34Radius * 0.3) * Math.Cos(parD12));
                body = Graphics3D.CreateCylinder(startPoint, endPoint, parD16, true);
                m_Physical.Outputs.Add("CylinderBody6", body);
                //Insulation
                //Nozz3BodyIns
                double maxDiameter = ReturnMax4(port3.PipingOutsideDiameter * 2, port3.PipingOutsideDiameter * 2, 0, 0);
                startPoint = new Position(-parD4 * 0.5 - parD3 - parD2 + parD7, parD9 * Math.Sin(parD11), parD9 * Math.Cos(parD11));
                endPoint = new Position(-parD4 * 0.5 - parD3 - parD2 + parD7, 0, 0);
                body = Graphics3D.CreateCylinder(startPoint, endPoint, maxDiameter + 2 * parInsulationThickness, true);
                m_Insulation.Outputs.Add("Nozz3BodyIns", body);

                //Nozz4BodyIns
                maxDiameter = ReturnMax4(port4.PipingOutsideDiameter * 2, port4.PipingOutsideDiameter * 2, 0, 0);
                startPoint = new Position(-parD4 * 0.5 - parD3 - parD2 + parD8, parD10 * Math.Sin(parD12), parD10 * Math.Cos(parD12));
                endPoint = new Position(-parD4 * 0.5 - parD3 - parD2 + parD8, 0, 0);
                body = Graphics3D.CreateCylinder(startPoint, endPoint, maxDiameter + 2 * parInsulationThickness, true);
                m_Insulation.Outputs.Add("Nozz4BodyIns", body);

                //VenturiBodyIns
                maxDiameter = ReturnMax4(port1.PipingOutsideDiameter * 2, port2.PipingOutsideDiameter * 2, port1.FlangeOrHubOutsideDiameter, port2.FlangeOrHubOutsideDiameter);

                startPoint = new Position(-parD4 * 0.5 - parD3 - parD2, 0, 0);
                endPoint = new Position(parD4 * 0.5 + parD5, 0, 0);
                body = Graphics3D.CreateCylinder(startPoint, endPoint, maxDiameter + 2 * parInsulationThickness, true);
                m_Insulation.Outputs.Add("VenturiBodyIns", body);

            }
            catch (Exception ex)
            {
                throw ex;
            }
        }


        #endregion
        public Double ReturnMax4(Double A, Double B, Double C, Double D)
        {
            Double MaxValue = A;
            if (MaxValue < B) { MaxValue = B; }
            if (MaxValue < C) { MaxValue = C; }
            if (MaxValue < D) { MaxValue = D; }
            return MaxValue;
        }

    }

}

